﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Data;
using System.Xml.Serialization;
using System.IO;

using EntityMap.Meta;
using System.Data.SqlClient;
using System.Reflection;
using System.Collections;

namespace EntityMap
{
    /// <summary>
    /// This is the main class, it contains information about
    /// mapping metadata repository and the ExecuteStatement<T> method.
    /// </summary>
    public partial class EntityMapper : IDisposable
    {
        private IEntityMapRepository _mapRepository = null;
        private TextWriter _tw = null;
        private Hashtable _maps;

        public event EventHandler<EntityMapEventArgs> OnExcutingStatement;
        public event EventHandler<EntityMapEventArgs> OnExcutedStatement;

        /// <summary>
        /// A database connection string 
        /// </summary>
        public string ConnectionString { get;set; }

        /// <summary>
        /// Writer for Sql tracking,
        /// useful for debugging.
        /// </summary>
        public TextWriter Out
        {
            set { _tw = value; }
        }

        public EntityMapper( string connectionString )
            : this( connectionString, new XmlFileEntityMapRepository() )
        {   
        }
      
        public EntityMapper( string connectionString, IEntityMapRepository mapRepository )
        {
            ConnectionString = connectionString;
            _maps = new Hashtable();

            _mapRepository = mapRepository;
        }

        /// <summary>
        /// Get mapping metadata of specific entity
        /// </summary>
        /// <param name="entityType"></param>
        /// <returns></returns>
        public EntityInfo GetEntityInfo( Type entityType )
        {
            // check cache
            if( _maps.ContainsKey( entityType.Name ) )
            {
                return _maps[entityType.Name] as EntityInfo;
            }

            // load metadata information from metadata repository
            EntityInfo einfo = _mapRepository.GetEntityInfo( entityType );

            // substitute alias string
            einfo.ApplyAlias();

            // add metadata to cache
            _maps.Add( entityType.Name, einfo );

            return einfo;
        }

        /// <summary>
        /// Persist mapping metadata inforation.
        /// </summary>
        /// <param name="entityType">Type of entity.</param>
        /// <param name="entityInfo">Entity mapping metadata.</param>
        public void SaveEntityInfo( Type entityType, EntityInfo entityInfo )
        {
            _mapRepository.SaveEntityInfo( entityType, entityInfo );
        }

        public void ClearCache()
        {
            _maps = new Hashtable();
        }

        public void Dispose()
        {
            ClearCache();
        }

    }
}
